package cn.ant.utils;

import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @Version 1.0
 * @Author:lss
 * @Date:2021/10/7
 * @Content: 日志
 */
@Slf4j
@Aspect
@Component
@Scope("prototype")
public class AopTimerLog {
    @Autowired
    private ObjectMapper objectMapper;
    //开始时间
    private Long startTime;
    //访问的类
    private Class clazz;
    //访问的方法
    private Method method;
    //格式化时间
    String strDateFormat = "yyyy-MM-dd HH:mm:ss";
    SimpleDateFormat dateFormat = new SimpleDateFormat(strDateFormat);

    /**
     * 声明切点
     */
    @Pointcut("@within(cn.ant.annotation.AopTimerLog)")//类生效
//    @Pointcut("@annotation(cn.ant.annotation.AopTimerLog)")//方法生效
    private void aspect(){}

    /**
     * 前置通知
     * @param joinPoint
     */
    @Before(value = "aspect()")
    public void before(JoinPoint joinPoint) throws NoSuchMethodException {
        //开始时间
        startTime=System.currentTimeMillis();
        String formatDate = dateFormat.format(new Date(startTime));
        //切入点的类对象
        clazz = joinPoint.getTarget().getClass();
        //切入点
        String methodName = joinPoint.getSignature().getName();
        //切入点参数
        Object[] args = joinPoint.getArgs();
        //是否为有参
        if (args==null||args.length==0){
            method=clazz.getMethod(methodName);
        }else {
            Class[] argsClazz = new Class[args.length];
            for (int i = 0; i < args.length; i++) {
                //参数的类对象
                argsClazz[i]=args[i].getClass();
            }
            //有参方法
            method=clazz.getMethod(methodName,argsClazz);
        }
        log.info("开始时间 {}",formatDate);
        log.info("类名{}，方法名{}，参数{}",clazz.getName(),method.getName(),method.getParameters());
    }

    @AfterReturning(returning = "object" ,pointcut = "aspect()")
    public void after(Object object){
        log.info("出参 {}",object);
        log.info("结束时间 {} ms",(System.currentTimeMillis()-startTime));
    }
}
